﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TextTemplating;
using EnvDTE;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell.Design;
using Microsoft.VisualStudio.Shell;
using System.Reflection;

namespace ScaffoldIt
{
    static class ModelHelpers
    {
        public static List<ScaffoldModel> GetModels(this ScaffoldingContext context)
        {
            var items = context.DTE.ToolWindows.SolutionExplorer.SelectedItems as Array;

            if (items == null)
                return null;

            List<ScaffoldModel> res = new List<ScaffoldModel>();

            foreach (UIHierarchyItem item in items)
            {
                var prjItem = item.Object as ProjectItem;
                res.Add(context.GetModelFor(prjItem));
            }

            return res;
        }

        private static ScaffoldModel GetModelFor(this ScaffoldingContext context, ProjectItem item)
        {
            ScaffoldModel model = null;
            var classes = item.FileCodeModel.CodeElements.GetClasses().ToList();
            if (classes.Count == 1)
            {
                var itemClass = classes[0];
                model = context.GetModelFor(item, itemClass);
            }

            return model;
        }

        public static ScaffoldModel GetModelFor(this ScaffoldingContext context, ProjectItem item, CodeClass itemClass)
        {
            ScaffoldModel model;
            model = new ScaffoldModel();
            //var realType = GetRealType(context.DTE, item.ContainingProject, itemClass);
            //if (realType != null)
            //{
            //    model.underlyingData = realType;
            //    FromRealType(realType, model);
            //}
            //else
            //{
            FromCodeClass(itemClass, model);
            //}
            
            return model;
        }

        private static void FromRealType(Type realType, ScaffoldModel model)
        {
            model.ClassName = realType.Name;
            model.PluralizedClassName = model.ClassName.Pluralize(); 
            model.FullName = realType.FullName;
            model.Namespace = realType.Namespace;
            model.Properties = realType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(
                p =>
                {
                    return new ScaffoldModelProperties()
                    {
                        Name = p.Name,
                        Type = p.PropertyType.Name,
                        TypeFullName = p.PropertyType.FullName,
                        Visibility = "public",
                        underlyingData = p
                    };
                }).ToList();
        }

        private static void FromCodeClass(CodeClass itemClass, ScaffoldModel model)
        {
            model.ClassName = itemClass.Name;
            model.PluralizedClassName = model.ClassName.Pluralize(); 
            model.FullName = itemClass.FullName;
            model.Namespace = itemClass.Namespace.Name;
            model.Properties = itemClass.PublicProperties().Select(
                p =>
                    {
                        return new ScaffoldModelProperties()
                            { 
                                Name = p.Name, 
                                Type = p.Type.AsString,
                                TypeFullName = p.Type.AsFullName,
                                Visibility = "public" };
                    }).ToList();
        }

        private static Type GetRealType(EnvDTE80.DTE2 DTE, Project project, CodeClass itemClass)
        {
            IVsSolution solution = (IVsSolution)Package.GetGlobalService(typeof(IVsSolution)); 
            DynamicTypeService typeResolver = (DynamicTypeService)Package.GetGlobalService(typeof(DynamicTypeService)); 
            IVsHierarchy hierarchy = null; solution.GetProjectOfUniqueName(project.UniqueName, out hierarchy); 
            var _typeResolutionService = typeResolver.GetTypeResolutionService(hierarchy);
            
            return _typeResolutionService.GetType(itemClass.FullName);
        }
    }
}
